#pragma once

#include <memory>

#include "Socket.hpp"
#include "nocopy.hpp"
#include "Threads.hpp"

template <class T>
class Server : public nocopy
{
public:
    //在创建Server的时候，直接完成定义，并且拿到Server的thread要执行的函数方法
    Server(in_port_t port, T task)
        : _server_usage(new ServerSocket(port)), _task(task)
    {
        _server_usage->ServerInit();
    }

    //启动server
    //1. 让主线程进行获取连接，新线程完成IO
    void Running()
    {
        Thread<void*> thread(std::bind(&Server<T>::ThreadFunc, this));
        while (true)
        {
            // 主线程一直去获取连接
            _server_usage->SocketAccept(); //获取失败直接退出，成功就往下，没有可以获取的就阻塞
            thread.Start();  //线程运行
        }
    }

    void* ThreadFunc()
    {
        // 1. server端拿到数据
        std::string datagram;
        _server_usage->Recv(datagram);
        // 2. 处理数据
        std::string send_str = _task(datagram);
        // 3. 发送回去
        _server_usage->Send(send_str);
        // 4. 关闭打开的文件描述符，防止文件描述符表溢出
        close(_server_usage->GetSockfd());
        return nullptr;
    }

private:
    std::shared_ptr<Socket> _server_usage;
    T _task;
};
